package framework.ui;

import org.openems.entity.Entity;
import org.openems.entity.Key;
import org.openems.entity.ListEntity;
import org.openems.entity.TraceEntity;

import framework.DomainService;
import framework.EntityStoreListener;
import javafx.scene.chart.Axis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;

public class EmsLineChart extends Pane implements IChart {
	private LineChart<Number, Number> chart;
	private AnchorPane plotPane = new AnchorPane();
	private DomainService service;
	private Key key;
	
	public EmsLineChart(Key key, DomainService service) {
		this.service = service;
		this.key = key;

		NumberAxis yAxis = new NumberAxis(-20, 20, 1);
		NumberAxis xAxis = new NumberAxis(0, 10, 1);
		
		chart = new LineChart<Number, Number>(xAxis, yAxis);
		chart.prefHeightProperty().bind(this.heightProperty());
		chart.prefWidthProperty().bind(this.widthProperty());
		chart.setLegendVisible(false);
		
		this.getChildren().add(chart);
		this.getChildren().add(plotPane);
		
		plotPane.prefHeightProperty().bind(chart.heightProperty());
		plotPane.prefWidthProperty().bind(chart.widthProperty());	
		
		createChart(chart, service, key);
		
		this.setWidth(500);
		this.setHeight(300);
	}

	private void createChart(LineChart<Number, Number> chart2,
			DomainService service2, Key key2) {
		TraceEntity entity = (TraceEntity)service.getEntity(key);
		
		chart.getYAxis().setLabel(entity.getVerticalAxisName());
		chart.getXAxis().setLabel(entity.getHorizontalAxisName());
		chart.getYAxis().setAutoRanging(true);
		chart.getXAxis().setAutoRanging(false);
		service.addEntityStoreListener(new EntityStoreListener() {
			@Override
			public void valueChanged(Entity entity) {
				updateChart((TraceEntity)entity, chart);
			}			
		}, key);
	}

	protected void updateChart(TraceEntity entity,
			LineChart<Number, Number> chart2) {
		
		XYChart.Series<Number, Number> series = new XYChart.Series<Number, Number>();
		
		Double xstep = entity.getHorizontalMax() / (double)entity.getData().length;
		double mag = 1.0;
		double step = (double)entity.getData().length / chart.getWidth()/mag;
        for (int i = 0; i < chart.getWidth() * mag; i++) {
        	int ii = (int)(i * step);
            double y = entity.getData()[ii];
            double x = entity.getHorizontalMin() + xstep * (double)(ii);
            series.getData().add(new XYChart.Data<Number, Number>(x, y));
        }
        ((NumberAxis)chart.getXAxis()).setLowerBound(entity.getHorizontalMin());
        ((NumberAxis)chart.getXAxis()).setUpperBound(entity.getHorizontalMax());
        chart.getData().clear();
        chart.createSymbolsProperty().set(false);
        chart.animatedProperty().set(false);
        chart.getData().add(series);
        chart.setEffect(null);
        chart.getData().get(0).getNode().setStyle("-fx-stroke-width:1");
	}

	public void addMarker(Key markerKey) {
		IChart ichart = new IChart() {
			@Override
			public Double getXValue(double value) {
				return chart.getXAxis().getValueForDisplay(
						value - chart.getPadding().getLeft() - chart.getXAxis().getLayoutX()
						).doubleValue();
			}

			@Override
			public double getXLocation(Double value) {
				Axis<Number> xAxis = chart.getXAxis();
				return xAxis.localToParent(xAxis.getDisplayPosition(value), 0).getX() + chart.getPadding().getLeft();
			}

			@Override
			public double getYLocation(Double value) {
				Axis<Number> yAxis = chart.getYAxis();
				return yAxis.localToParent(0, yAxis.getDisplayPosition(value)).getY() + chart.getPadding().getTop();
			}
			
		};
		plotPane.getChildren().add(new EmsMarkerIcon(markerKey, ichart, service));
	}

	public void addMarkerList(Key keyList) {
		ListEntity keys = (ListEntity)service.getEntity(keyList);
		for (Key k : keys.getKeys()) {
			addMarker(k);
		}
		service.addEntityStoreListener(new EntityStoreListener() {
			@Override
			public void valueChanged(Entity entity) {
				plotPane.getChildren().clear();
				for (Key markerKey : ((ListEntity)entity).getKeys()) {
					addMarker(markerKey);
				}
			}
		}, keyList);
	}

	@Override
	public Double getXValue(double value) {
		return chart.getXAxis().getValueForDisplay(
				value - chart.getPadding().getLeft() - chart.getXAxis().getLayoutX()
				).doubleValue();
	}

	@Override
	public double getXLocation(Double value) {
		Axis<Number> xAxis = chart.getXAxis();
		return xAxis.localToParent(xAxis.getDisplayPosition(value), 0).getX() + chart.getPadding().getLeft();
	}

	@Override
	public double getYLocation(Double value) {
		Axis<Number> yAxis = chart.getYAxis();
		return yAxis.localToParent(0, yAxis.getDisplayPosition(value)).getY() + chart.getPadding().getTop();
	}

	public void addMarker(Pane marker) {
		plotPane.getChildren().add(marker);
	}
}
